package com.bsj.media.network;

import com.alibaba.fastjson.JSONObject;
import com.bsj.consumerQ.until.ExceptionUntil;
import com.bsj.media.init.CachedChannelMap;
import com.bsj.media.init.NettyConnectUntil;
import com.bsj.media.init.SendChannelUntil;
import com.bsj.media.network.download.ExportFileUtil;
import com.bsj.power.common.helper.GeoHashConstants;
import com.bsj.power.common.util.ExceptionUtil;
import com.bsj.power.common.util.SpringUtil;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.MemoryAttribute;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import redis.clients.bsj.JedisClusterBSJ;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
public class HttpRequestHandler extends SimpleChannelInboundHandler<Object> {

    private final JedisClusterBSJ jedisClusterBSJ = SpringUtil.getBean(JedisClusterBSJ.class);

    private final static String URL ="/live/gainLink";
    private final static String DOWNLOAD_URL ="/live/download";

    public HttpRequestHandler() {

    }

    private Map<String, String> getRequestParams(FullHttpRequest req) {
        Map<String, String> requestParams = new HashMap<>();
        HttpMethod method = req.method();
        // 处理get请求
        if (HttpMethod.GET.equals(method)) {
            QueryStringDecoder decoder = new QueryStringDecoder(req.uri());
            Map<String, List<String>> paramMap = decoder.parameters();
            if (paramMap != null && !paramMap.isEmpty()) {
                for (Map.Entry<String, List<String>> entry : paramMap.entrySet()) {
                    requestParams.put(entry.getKey(), entry.getValue().get(0));
                }
            }
        }
        // 处理POST请求
        if (HttpMethod.POST.equals(method)) {
            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), req);
            List<InterfaceHttpData> postData = decoder.getBodyHttpDatas(); //
            for (InterfaceHttpData data : postData) {
                if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                    MemoryAttribute attribute = (MemoryAttribute) data;
                    requestParams.put(attribute.getName(), attribute.getValue());
                }
            }
        }
        return requestParams;
    }

    //netty未处理的异常都会在这里
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        if (!cause.getLocalizedMessage().equals("Connection reset by peer")) {
            log.error("系统 exceptionCaught: " + ExceptionUntil.getErrorStr(cause));
        }
        //发生异常关闭链路
        NettyConnectUntil.del(ctx);
    }

    //设备链接上来
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelActive();
        NettyConnectUntil.add(ctx);
    }

    // 客户端连接关闭
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        NettyConnectUntil.del(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state().equals(IdleState.ALL_IDLE)) {
                ctx.channel().close().addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        log.info("closeChannel: close the connection to remote address[" + future.isSuccess());
                    }
                });
            }
        }

        ctx.fireUserEventTriggered(evt);
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            if (msg instanceof FullHttpRequest) {
                FullHttpRequest fullHttpRequest = (FullHttpRequest) msg;
                String uri = fullHttpRequest.uri();
//                if (uri.contains(DOWNLOAD_URL) && fullHttpRequest.method().equals(HttpMethod.GET)) {
//                    //文件下载
//                    ExportFileUtil.responseExportFile(ctx, "D://model.txt", "model.txt");
//                    return;
//                }
                if (uri.contains(URL)) {
                    Map<String, String> paramMap = getRequestParams(fullHttpRequest);
                    String simChannelData = paramMap.get("simChannel");
                    String downFile = paramMap.get("downFile");
                    //多媒体格式
                    String mediaType = paramMap.get("mediaType") == null ? "" : paramMap.get("mediaType");
                    log.info("传入参数:" + simChannelData);
                    if (!StringUtils.isEmpty(simChannelData)) {
                        if (simChannelData.indexOf("undefined") >= 0) {
                            log.warn("参数不符合规范:" + simChannelData);
                            ctx.close();
                            return;
                        }
                        String[] simChannelStr = simChannelData.split(".flv");
                        //3-1 || 3-127-port
                        String simChannel = simChannelStr[0];
//                        if (simChannel.length() == 11) {
//                            simChannel = "0" + simChannel;
//                        }
                        String[] split = simChannel.split("-");
                        //通道号 回放会加126
                        int intChannel = GeoHashConstants.changeInt(split[1]);

                        if (com.bsj.power.common.util.StringUtils.isNotEmpty(downFile)) {
                            log.info("下载链路连接： {}", simChannel);
                            //下载
                            SendChannelUntil.addHttpDownVideo(simChannel, ctx, downFile, mediaType);
                        } else {
                            log.info("多媒体观看连接： {}", simChannel);
                            //直播
                            if (intChannel < 126) {
                                SendChannelUntil.addHttpLiveVideo(simChannel, ctx, mediaType);
                            } else {
                                //回放 3-127-port
//                            SendChannelUntil.addHttp(simChannel, ctx);
                                SendChannelUntil.addHttpLiveVideo(simChannel, ctx, mediaType);
                            }
                        }
                        //缓存通道对应的播放列表
                        CachedChannelMap.push(ctx, simChannel);
                        //用于延迟关闭连接
//                        CloseThread.removeChannel(simChannel);
                        NettyConnectUntil.push(ctx);
                    } else {
                        log.warn("链接给的不对:" + JSONObject.toJSONString(paramMap));
                        //无效链接直接关闭
                        ctx.close();
                    }
                } else {
                    ctx.close();
                }
            }
        } catch (Exception e) {
            log.error(ExceptionUtil.getStackStr(e));
        }
    }

}
